package metrics

import "time"

// IndicData 单个指标数据
type IndicData struct {
	Name       string
	Value      float64
	Unit       string
	AggrMethod IndicAggrMethod   //聚合方式
	AggrScope  time.Duration     //聚合时间范围,最小单位为秒
	Labels     map[string]string //标签
	Time       int64             //指标对应时间，单位：毫秒级时间戳
}

func (ind IndicData) Append(cur IndicData) IndicData {
	return cur.AggrMethod.Aggr(ind, cur)
}

func (ind IndicData) EntireLabels() map[string]string {
	var m = ind.Labels
	if m == nil {
		m = map[string]string{}
	}

	m["metric"] = ind.Name
	m["unit"] = ind.Unit

	return m
}

type IndicAggrMethod string

const (
	AggrByCount IndicAggrMethod = "count" //求和
	AggrBySum   IndicAggrMethod = "sum"   //求和
	AggrByAvg   IndicAggrMethod = "avg"   //求平均
	AggrByMax   IndicAggrMethod = "max"   //求最大值
	AggrByMin   IndicAggrMethod = "min"   //最小值
)

func (m IndicAggrMethod) Aggr(old IndicData, cur IndicData) IndicData {
	var v = old.Value
	if cur.Value == 0 && m == AggrByCount {
		cur.Value = 1
	}

	//超过聚合时间范围则取最新的
	if (cur.Time - old.Time) > cur.AggrScope.Milliseconds() {
		return cur
	}

	switch m {
	case AggrByCount:
		v += cur.Value
	case AggrBySum:
		v += cur.Value
	case AggrByAvg:
		v = (v + cur.Value) / 2
	case AggrByMax:
		if cur.Value > v {
			v = cur.Value
		}
	case AggrByMin:
		if cur.Value < v {
			v = cur.Value
		}
	}
	return IndicData{
		Name:       cur.Name,
		Value:      v,
		Unit:       cur.Unit,
		AggrMethod: cur.AggrMethod,
		AggrScope:  cur.AggrScope,
		Labels:     cur.Labels,
		Time:       old.Time, //聚合后时间取旧数据的时间
	}
}
